#include "MLTools_Stat.h"
_MYLABLIB_BEGIN
CMLTools_Stat::CMLTools_Stat(void)
{
}

CMLTools_Stat::~CMLTools_Stat(void)
{
}

CMLDataPoint CMLTools_Stat::CalCentroid(const CMLDataSet &dataSet)
{
	CMLDataPoint centroid;
	// Calculate the centroid
	if (dataSet.IsEmpty())
		return centroid;
	centroid = dataSet.Get(0);
	int i;
	for (i=0; i<dataSet.Count(); i++)
		centroid.add(dataSet.Get(i));
	centroid.div((double)dataSet.Count());
	return centroid;
}

double CMLTools_Stat::CalStandardDeviation(const CMLDataSet& dataSet, IMLDataPointDistanceFunc* pDistFunc)
{
	CMLDataPoint centroid = CalCentroid(dataSet);
	int i;
	double SquaredSum = 0;
	for (i=0; i<dataSet.Count(); i++)
	{
		double dist = pDistFunc->Distance(dataSet.Get(i), centroid);
		SquaredSum += dist*dist;
	}
	SquaredSum /= dataSet.Count();
	return sqrt(SquaredSum);
}

double CMLTools_Stat::CalSSQ(const std::vector<CMLDataSet>& vClusters, IMLDataPointDistanceFunc* pDistFunc)
{
	int nClusterIndex;
	double dSSQ = 0.0;
	for (nClusterIndex=0; nClusterIndex<(int)vClusters.size(); nClusterIndex++)
	{
		const CMLDataSet& cluster = vClusters[nClusterIndex];
		// Calculate the centroid
		if (cluster.IsEmpty())
			continue;
		CMLDataPoint centroid = CMLTools_Stat::CalCentroid(cluster);
		int i;
		// Calculate the square sum
		for (i=0; i<cluster.Count(); i++)
		{
			dSSQ += pDistFunc->Distance(centroid, cluster.Get(i));
		}
	}
	return dSSQ;
}

double CMLTools_Stat::CalSSQ(const std::vector<CMLDataCluster>& vClusters, IMLDataPointDistanceFunc* pDistFunc)
{
	int nClusterIndex;
	double dSSQ = 0.0;
	for (nClusterIndex=0; nClusterIndex<(int)vClusters.size(); nClusterIndex++)
	{
		const CMLDataCluster& cluster = vClusters[nClusterIndex];
		// Calculate the centroid
		if (cluster.dataset.IsEmpty())
			continue;
		int i;
		// Calculate the square sum
		for (i=0; i<cluster.dataset.Count(); i++)
		{
			dSSQ += pDistFunc->Distance(cluster.center, cluster.dataset.Get(i));
		}
	}
	return dSSQ;
}

double CMLTools_Stat::CalSSQ(const CMLDataSet& dataSet, const std::vector<CMLDataPoint>& vCenters, IMLDataPointDistanceFunc* pDistFunc)
{
	double dSSQ = 0.0;
	int i;
	for (i=0; i<dataSet.Count(); i++)
	{
		int nCenterIndex;
		double dMinDist = DBL_MAX;
		CMLDataPoint point = dataSet.Get(i);
		for (nCenterIndex=0; nCenterIndex<(int)vCenters.size(); nCenterIndex++)
		{
			double dDist = pDistFunc->Distance(point, vCenters[nCenterIndex]);
			if (dDist < dMinDist)
			{
				dMinDist = dDist;
			}
		}
		dSSQ += dMinDist;
	}
	return dSSQ;
}

_MYLABLIB_END